package com.witframework.web.tag;


import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyContent;
import javax.servlet.jsp.tagext.BodyTagSupport;
/**
 *     
 *     Custom JSP taglib lets you periodically perform Ajax requests. Taglib defines a timer that asynchronously requests your server side (JSP, servlet). For example:
 

<script language="JavaScript" src="cjajax.js"></script>

<%@ taglib uri="taglib.tld" prefix="a" %>

<a:AjaxTimer id="i1" url="newContent.jsp" timeout="10" handler="myHandler">

In this example your file newContent.jsp will be requested each 10 seconds.

An optional parameter handler lets you provide your own JavaScript function that will accept the requested data. This function will get two parameters: obtained text and obtained XML document:
 

<script language="JavaScript">
function myHandler(txt, xmlDoc)
{
  your own processing for the requested content
}
</script>

an optional parameter error lets you provide your own error handler for failed requests:

<script language="JavaScript" src="cjajax.js"></script>

<script language="JavaScript">
function onError() { alert("Count not get data"); }
</script>

Attributes beforeAction and afterAction lets you provide your own JavaScript code that marks start/end phase of request. For example you can show/hide here some loading image etc. So, you can describe in your HTML code some progress indicator:
 

<div style="display:none" id="loading"><img src="loading.gif"/></div>

and define two JavaScript functions:
 

function beforeAction()
{
document.getElementById("loading").style.display="block";
}

function afterAction()
{
document.getElementById("loading").style.display="none";
}

it lets you show/hide progress indicator

Timeout will be available through the JavaScript variable described in the attribute id. E.g. in the above mentioned example (timer id is i1) you can stop process by this call: clearTimeout(i1).

In order to use this tag you have to describe an external JavaScript file cjajax.js on your page.

Url used for the server side request could be calculated in some JavaScript function. It is described in the attribute urlFunction. See JavaScript link taglib also. E.g. the typical use case when your own function collects data from some form and returns the target url with parameters.

A negative value for timeout attribute simply disables the requests.

Tags are:

AjaxTimer

Tag defines Ajax based timer. Parameters are:

1) url Optional parameter. Describes an URL for your requests.
2) urlFunction Optional parameter. Describes a function that will return an url.
3) handler Optional parameter. Describes a name for your own JavaScript function that will accept the requested content. By default this function is empty.
4) error Optional parameter. Describes a name for your own JavaScript function that will be called in case of errors. By default is empty.
5) timeout Optional parameter. Describes a timeout for the periodical calls (in seconds). Default value is 10.
6) id Optional parameter. Describes an id for your timer.
7) beforeAction Optional parameter. Describes a name for your own JavaScript function that will be called at the beginning of request. By default is empty.
8) afterAction Optional parameter. Describes a name for your own JavaScript function that will be called at the end of request. By default is empty.
 

 * @author wuxinyang
 * Aug 17, 2009 12:29:23 PM
 *
 */
public class AjaxTimerTag extends BodyTagSupport
{
  private static final String AJAX_TIMER_TAG = "jxtmrtgcj2006";
  private String url = null;
  private String handler = null;
  private String timeout = "10";
  private String error = null;
  private String urlFunction = null;
  private String id = null;
  private String beforeAction = null;
  private String afterAction = null;
  private String sBody = null;

  public void setBeforeAction(String paramString)
  {
    this.beforeAction = paramString;
  }

  public String getBeforeAction()
  {
    return this.beforeAction;
  }

  public void setAfterAction(String paramString)
  {
    this.afterAction = paramString;
  }

  public String getAfterAction()
  {
    return this.afterAction;
  }

  public String getUrl()
  {
    return this.url;
  }

  public void setUrl(String paramString)
  {
    this.url = paramString;
  }

  public void setHandler(String paramString)
  {
    this.handler = paramString;
  }

  public String getHandler()
  {
    return this.handler;
  }

  public void setUrlFunction(String paramString)
  {
    this.urlFunction = paramString;
  }

  public String getUrlFunction()
  {
    return this.urlFunction;
  }

  public void setError(String paramString)
  {
    this.error = paramString;
  }

  public String getError()
  {
    return this.error;
  }

  public void setTimeout(String paramString)
  {
    this.timeout = paramString;
  }

  public String getTimeout()
  {
    return this.timeout;
  }

  public int doAfterBody()
    throws JspException
  {
    BodyContent localBodyContent = getBodyContent();
    if (localBodyContent == null)
    {
      this.sBody = "";
    }
    else
    {
      this.sBody = localBodyContent.getString();
      localBodyContent.clearBody();
    }
    this.sBody = this.sBody.trim();
    return 0;
  }

  public int doEndTag()
    throws JspException
  {
    StringBuffer localStringBuffer = new StringBuffer(" ");
    if ((this.url == null) && (this.urlFunction == null))
      throw new JspException("AjaxTimer: you have to provide either url or urlFunction parameters");
    if ((this.url != null) && (this.urlFunction != null))
      throw new JspException("AjaxTimer: you have to provide either url or urlFunction parameters");
    int i = getInteger(this.timeout);
    if (i <= 0)
    {
      dropData();
      return 6;
    }
    long l = i * 1000;
    if (this.id == null)
    {
      Integer localInteger = (Integer)this.pageContext.getAttribute("jxtmrtgcj2006", 1);
      if (localInteger == null)
        localInteger = new Integer(0);
      this.id = "ajax_timer" + localInteger.intValue();
      this.pageContext.setAttribute("jxtmrtgcj2006", new Integer(localInteger.intValue() + 1), 1);
    }
    localStringBuffer.append("\n<script language=\"JavaScript\" type=\"text/javascript\">\n");
    localStringBuffer.append("var " + this.id + "=null;");
    localStringBuffer.append("function handler_");
    localStringBuffer.append(this.id);
    localStringBuffer.append("(){");
    localStringBuffer.append("cjAjaxEngine(");
    if (this.url != null)
    {
      localStringBuffer.append("'");
      localStringBuffer.append(this.url);
      localStringBuffer.append("'");
    }
    else
    {
      localStringBuffer.append(this.urlFunction);
      localStringBuffer.append("()");
    }
    localStringBuffer.append(",");
    if (this.handler != null)
      localStringBuffer.append(this.handler);
    else
      localStringBuffer.append("emptyHandler");
    localStringBuffer.append(",");
    if (this.error == null)
      localStringBuffer.append("null");
    else
      localStringBuffer.append(this.error);
    if (this.beforeAction == null)
      localStringBuffer.append(",null");
    else
      localStringBuffer.append("," + this.beforeAction);
    if (this.afterAction == null)
      localStringBuffer.append(",null");
    else
      localStringBuffer.append("," + this.afterAction);
    localStringBuffer.append(");");
    localStringBuffer.append(this.id + "=setTimeout('handler_" + this.id + "()'," + l + ");");
    localStringBuffer.append("}\n");
    localStringBuffer.append(this.id + "=setTimeout('handler_" + this.id + "()'," + l + ");\n");
    localStringBuffer.append("</script>\n");
    try
    {
      this.pageContext.getOut().write(localStringBuffer.toString());
    }
    catch (Exception localException)
    {
      throw new JspException("AjaxTimer: could not write data");
    }
    dropData();
    return 6;
  }

  public void release()
  {
    dropData();
  }

  private void dropData()
  {
    this.url = null;
    this.handler = null;
    this.timeout = "10";
    this.error = null;
    this.urlFunction = null;
    this.id = null;
    this.sBody = null;
    this.beforeAction = null;
    this.afterAction = null;
  }

  private int getInteger(String paramString)
  {
    int i = -1;
    if (paramString == null)
      return i;
    try
    {
      i = Integer.parseInt(paramString);
    }
    catch (Exception localException)
    {
      return i;
    }
    return i;
  }
}